﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Nuanyang.Asp.Net.Core.Extension.DataBase;
using Nuanyang.Asp.Net.Core.Extension.Utils;

namespace Nuanyang.Asp.Net.Core.Extension.Middleware
{
    public class PermissionMiddleware 
    {
        private readonly RequestDelegate _next;
        private readonly string _claimName;
        private readonly FunctionContext _functionContext;

        /// <summary>
        /// 鉴权中间件
        /// </summary>
        /// <param name="next">下一个中间件</param>
        /// <param name="action">DBContextBuild</param>
        /// <param name="claimName">用户的组id在用户chaims的名字</param>
        public PermissionMiddleware(RequestDelegate next, FunctionContext functionContext, string claimName)
        {
            _next = next;
            _claimName = claimName;
            _functionContext = functionContext;
        }

        /// <summary>
        /// 鉴权(目前只允许一个用户对一个组，一对多后续添加)
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task Invoke(HttpContext context)
        {
            //从缓存鉴权

            //从数据库鉴权
            return FindInSql(context);
        }

        /// <summary>
        /// 从数据库中鉴权
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        private  Task FindInSql(HttpContext context)
        {
            var data = context.GetEndpoint();
            if (data == null)
            {
                //没找到对应的controller 和 method
                context.Response.StatusCode = StatusCodes.Status404NotFound;
                return Task.CompletedTask;
            }
            //判断接口是否是开放接口
            var function = _functionContext.Function.AsNoTracking().FirstOrDefault(c => c.FunctionName == data.DisplayName && c.IsDeleted == false && c.IsEnable == true);
            if (function != null && function.IsOpen)
            {
                //无需登录和身份认证的接口
                // 管道向下执行
                return this._next(context);
            }
            //判断用户组是否有访问权限
            var group = context.User.Claims.FirstOrDefault(c => c.Type == _claimName);
            //临时测试
            group = new System.Security.Claims.Claim("role","[2,1]");
            if (group != null && function != null)
            {
                List<long>  groupList = Newtonsoft.Json.JsonConvert.DeserializeObject<List<long>>(group.Value);
                foreach(long groupId in groupList)
                { 
                    if (!_functionContext.Group.AsNoTracking().Any(c => c.IsEnable == true && c.IsDeleted == false && c.Id == groupId))
                    {
                        continue;
                    }
                    //判断用户组是否有当前方法权限，有则管道向下执行没有则直接停止提示未授权
                    if (_functionContext.GroupFunction.AsNoTracking().Any(c => c.FunctionId == function.Id && c.GroupId == groupId && c.IsDeleted == false && c.IsEnable == true))
                    {
                        // 管道向下执行
                        return this._next(context);
                    }
                }
            }
            //用户未授权
            context.Response.StatusCode = StatusCodes.Status401Unauthorized;
            return Task.CompletedTask;
        }
    }
}
